#include "PlayState.h"
//
//const int kMaxBullets = 100;
//Bullet mGun1[kMaxBullets];

PlayState::PlayState(GameContext& gc)
	: GameState(gc)
	,mBulletIndex(0)
	,mEnemyIndex(0)
	,mExplosionIndex(0)
	,IsGameOver(false)
	//,mEnemyTypeAlimit(0)
	,mEnemyTypeBlimit(0)
	,mEnemyTypeClimit(0)
	,mLifecheck(3)
{
	mEnemyNum = kMaxEnemies;
}


void PlayState::FireBullets(float deltaTime)
{
	mDelay-=deltaTime;

	static float mTime=deltaTime;

	if(mTime>0.1f)
	{
		mGun1[--mBulletIndex].Kill();
	}

	// if space is pressed, fire mGun1
 if (!mGun1[mBulletIndex].IsActive())
 {
	mPos=mGun1[mBulletIndex].GetPosition();
	mVel=mGun1[mBulletIndex].GetVelocity();
	mPos+= mVel* deltaTime;
		
	if (Input_IsKeyPressed(Keys::UP)&&mDelay<=0.0f)
	{
	
		// middle bullet
		if (!mGun1[mBulletIndex].IsActive())
		{
			SVector2 pos = mCharacter.GetPosition();
			pos.x=pos.x;
			pos.y=pos.y-50.0f;
			SVector2 vel(0.0f, -700.0f);
			mGun1[mBulletIndex].Fire(pos, vel);
			mBulletIndex = (mBulletIndex + 1) % kMaxBullets;
			mDelay = mGun1[mBulletIndex].GetLife();
			mDelay= 0.6f;
			if(mTime>0.1)
			{
				mGun1[--mBulletIndex].Kill();
			}
		}
		
	}

	else if (Input_IsKeyPressed(Keys::RIGHT)&&mDelay<=0.0f)
	{
		
	 if (!mGun1[mBulletIndex].IsActive())
		{
			SVector2 pos =mCharacter.GetPosition();
			pos.x=pos.x+50;
			pos.y=pos.y;
			SVector2 vel(700.0f, -1.0f);
			mGun1[mBulletIndex].Fire(pos, vel);
			mBulletIndex = (mBulletIndex+ 1) % kMaxBullets;
			mDelay = mGun1[mBulletIndex].GetLife();
			mDelay= 0.6f;
			
			
		}
	}	

	else if (Input_IsKeyPressed(Keys::LEFT)&&mDelay<=0.0f)
	{
		
	if (!mGun1[mBulletIndex].IsActive())
		{

			SVector2 pos = mCharacter.GetPosition();
			pos.x=pos.x-50;
			pos.y=pos.y;
			SVector2 vel(-700.0f, 1.0f);
			mGun1[mBulletIndex].Fire(pos, vel);
			mBulletIndex = (mBulletIndex + 1) % kMaxBullets;
			mDelay = mGun1[mBulletIndex].GetLife();
			mDelay= 0.6f;
			
			
		}
	}

	else if (Input_IsKeyPressed(Keys::DOWN)&&mDelay<=0.0f)
	{
		
	if (!mGun1[mBulletIndex].IsActive())
		{
			SVector2 pos = mCharacter.GetPosition();
			pos.x=pos.x;
			pos.y=pos.y+50.0f;
			SVector2 vel(0.0f, 700.0f);
			mGun1[mBulletIndex].Fire(pos, vel);
			mBulletIndex = (mBulletIndex + 1) % kMaxBullets;
			mDelay = mGun1[mBulletIndex].GetLife();
			mDelay= 0.6f;
		}
			
	}

 }

}


void PlayState::SpawnEnemy(float deltaTime)
{
	mSpawnDelay -= deltaTime;
	if (mSpawnDelay <= 0.0f)
	{ 
		mEnemyTypeCheck =  mEnemyA[mEnemyIndex].GetEnemyType();

		if(mEnemyTypeCheck == "A")
		{
		// spawn enemy
		if (!mEnemyA[mEnemyIndex].IsActive())
		{

			srand(time(NULL));
			mRandomSpawnCount = 1+ rand() %3;
			const int kWinWidth = IniFile_GetInt("WinWidth", 800);
			switch(mRandomSpawnCount)
			{
			case 1:
			{
			const float posX = kWinWidth * RandomFloat(3.0f, 5.0f);
			const float posY = -100.0f;
			SVector2 pos(posX, posY);
			mEnemyA[mEnemyIndex].Spawn(pos);
			break;
			}

			case 2:
			{

			const float posX = kWinWidth * RandomFloat(4.0f,5.1f);
			const float posY = -100.0f;
			SVector2 pos(posX, posY);
			mEnemyA[mEnemyIndex].Spawn(pos);
			break;

			}

			case 3:
			{
			
			const float posX = kWinWidth * RandomFloat(4.0f,5.2f);
			const float posY = -100.0f;
			SVector2 pos(posX, posY);
			mEnemyA[mEnemyIndex].Spawn(pos);
			break;
			}


			}
		

			
			/*if(mEnemyIndex<mEnemyTypeAlimit)
			{*/
			mEnemyIndex = (mEnemyIndex+ 1) % kMaxEnemies;
			/*}*/

			// reset delay time
			mSpawnDelay = RandomFloat(0.5f, 1.0f);
			
		}
		}
	}
}



void PlayState::CheckEnemyBulletCollision(int collisiontype,float deltaTime)
{

	for (int e = 0; e < kMaxEnemies; ++e)
	{
		if (mEnemyA[e].IsActive())
		{
			for (int b = 0; b < kMaxBullets; ++b)
			{
				if (mGun1[b].IsActive())
				{
					SCircle eCircle = mEnemyA[e].GetBoundingCircle();
					SCircle bCircle = mGun1[b].GetBoundingCircle();
					float xDiff = eCircle.center.x - bCircle.center.x;
					float yDiff = eCircle.center.y - bCircle.center.y;
					float dist = sqrt((xDiff * xDiff) + (yDiff * yDiff));
					float radii = eCircle.radius + bCircle.radius;

					if ( dist <= radii )
					{
						mEnemyA[e].Kill();
						mGun1[b].Kill();
						
						mExplosion[mExplosionIndex].SetPosition(eCircle.center);
						mExplosion[mExplosionIndex].Start(100.0f, true);
						mExplosionIndex = (mExplosionIndex + 1) % kMaxExplosions;
						--mEnemyNum;

						
						/*enemycheck=enemycheck-1;
						mEnemyTypeAlimit=mEnemyTypeAlimit-1;*/
						
					
						break;
						// explosion sound
					}
				}
			}
		}
	}
}

void PlayState::CheckPlayerBulletCollision(int collisiontype,float deltaTime) //bulletplayercollision
{	
	for (int b = 0; b < kMaxBullets; ++b)
	{
		if (mGun1[b].IsActive())
		{
			SCircle eCircle = mCharacter.GetBoundingCircle();
			SCircle bCircle = mGun1[b].GetBoundingCircle();
			float xDiff = eCircle.center.x - bCircle.center.x;
			float yDiff = eCircle.center.y - bCircle.center.y;
			float dist = sqrt((xDiff * xDiff) + (yDiff * yDiff));
			float radii = eCircle.radius + bCircle.radius;

			if ( dist <= radii )
			{
				mGun1[b].Kill();
				mCharacter.Kill();
				if(mLifecheck==3)
				{
					
					mLife[2].Kill();
					--mLifecheck;
				}

				else if(mLifecheck==2)
				{
					mLife[1].Kill();
					--mLifecheck;
				}

				else if(mLifecheck==1)
				{
					mLife[0].Kill();
					--mLifecheck;
				}


				
				mDelay-=deltaTime;	
				mExplosion[mExplosionIndex].SetPosition((eCircle.center));	
				mExplosion[mExplosionIndex].Start(100.0f, true);
				mExplosionIndex = (mExplosionIndex + 1) % kMaxExplosions; 
				if(mCharacter.IsDead())
				{
					IsGameOver = true;

				}
				
				break;
				// explosion sound

			}
		}
	}
}

void PlayState::CheckPlayerEnemyCollision(int collisiontype,float deltaTime)//  player/enemy collision
{
	if(!IsGameOver)
	{
	for (int e = 0; e < kMaxEnemies; ++e)
		{
		  if (mEnemyA[e].IsActive())
		   {
			SCircle eCircle = mCharacter.GetBoundingCircle();
			SCircle bCircle = mEnemyA[e].GetBoundingCircle();
			float xDiff = eCircle.center.x - bCircle.center.x;
			float yDiff = eCircle.center.y - bCircle.center.y;
			float dist = sqrt((xDiff * xDiff) + (yDiff * yDiff));
			float radii = eCircle.radius + bCircle.radius;

			if ( dist <= radii )
			  {
				mEnemyA[e].Kill();
				mCharacter.Kill();

				if(mLifecheck==3)
				{
					
					mLife[2].Kill();
					--mLifecheck;
				}

				else if(mLifecheck==2)
				{
					mLife[1].Kill();
					--mLifecheck;
				}

				else if(mLifecheck==1)
				{
					mLife[0].Kill();
					--mLifecheck;
				}


				
	
				mExplosion[mExplosionIndex].SetPosition((eCircle.center));	
				mExplosion[mExplosionIndex].Start(100.0f, true);
				mExplosionIndex = (mExplosionIndex + 1) % kMaxExplosions; 
				if(mCharacter.IsDead())
				{
					IsGameOver = true;
					break;

				}
				
				--mEnemyNum;
				
				
				
				
				/*enemycheck=enemycheck-1;
				mEnemyTypeAlimit=mEnemyTypeAlimit-1;
				*/
						

				break;
			  }
			}

		 }

	}
		
}


void PlayState::InitializeWaveEnemy(char* enemytype)
{
	/*if(enemytype=="EnemyTypeA")
	{

	mEnemyTypeAlimit=FileHandle.GetEnemyNumber("EnemyTypeA");
	
	enemycheck =mEnemyTypeAlimit;
	                
	mEnemyArr=new EnemyTypeA[mEnemyTypeAlimit];
	}
	*/

	/*else if(enemytype=="EnemyTypeB")
	{
		mEnemy2Arr=new EnemyTypeB[enemynum];
	}*/

		/*else if(enemytype=="EnemyTypeC")
	{
		mEnemy3Arr=new EnemyTypeC[enemynum];
	}*/
}




PlayState::~PlayState()
{

}

void PlayState::Load()
{
	
	/*mfilename="wavedata1.txt";
	
	FileHandle.LoadLevel(mfilename);
	InitializeWaveEnemy("EnemyTypeA");

	*/

	for(int i = 0;i < kMaxBullets ;++i)
	{

		mGun1[i].Load();

	}

	for(int i = 0;i <kMaxEnemies ;++i)
	{

		mEnemyA[i].Load();

	}

	for (int i = 0; i < kMaxExplosions; ++i )
	{
		
		mExplosion[i].Load("explosion.txt");
	}

	

	mCharacter.Load();



	for(int i= 0 ;i<3;++i)
	{
	    mLife[i].Load();
	
	
	}



	const int kWinWidth = IniFile_GetInt("WinWidth", 800);
	const int kWinHeight = IniFile_GetInt("WinHeight", 600);
	SVector2 startPosition(kWinWidth * 0.5f, kWinHeight * 0.8f);
	mCharacter.SetPosition(startPosition);


	SVector2 life1(mCharacter.GetPosition());
	life1.x-=100;
	life1.y-=-100;
	SVector2 life2(mCharacter.GetPosition());
	life2.y-=-100;
	SVector2 life3(mCharacter.GetPosition());
	life3.x+=100;
	life3.y-=-100;
	mLife[0].SetPosition(life1);
	mLife[1].SetPosition(life2);
	mLife[2].SetPosition(life3);


	mWaveFont.Load(140);

	mExitScreen.Load("space.jpg");
	mFont.Load(20);
	mCursor.Load("sword.png");

	mStartButton1.Load("button_on.png","button_off.png");
	mStartButton1.SetPosition(SVector2(200.0f,500.0f));
	mStartButton1.SetText("Retry?",255,255,255);


	mQuitButton.Load("button_on.png","button_off.png");
	mQuitButton.SetPosition(SVector2(200.0,600.0f));
	mQuitButton.SetText("Quit?",255,255,255);
	


	
	char levelName[256];
	char texturePackName[256];
	sprintf_s(levelName,256,"level0%d.txt",mGameContext.GetLevel());
	sprintf_s(texturePackName,256,"texturepack01.txt",mGameContext.GetLevel());
	mmap.Load(levelName,texturePackName);
	

}

void PlayState::Unload()
{
	mmap.Unload();
	
	for(int i= 0 ;i<3;++i)
	{
	mLife[i].Unload();
	}

	mCharacter.Unload();
	for(int i = 0;i < kMaxBullets;++i)
	{

		mGun1[i].Unload();
	}

	for(int i = 0;i <kMaxEnemies;++i)
	{

		mEnemyA[i].Unload();
	}

	for (int i = 0; i < kMaxExplosions; ++i )
	{
		
		mExplosion[i].Unload();
	}

	mFont.Unload();
	mWaveFont.Unload();
	mExitScreen.Unload();
	mCursor.Unload();
	mStartButton1.Unload();
	mQuitButton.Unload();
	
}

NextState PlayState::Update(float deltaTime)
{

	
	
	for (int i = 0;i<kMaxBullets;++i)
	{
		mGun1[i].Update(deltaTime,mmap);
	}

	for (int i = 0;i<kMaxEnemies;++i)
	{
		
		mEnemyA[i].Update(deltaTime,mmap);
	}

	for (int i = 0; i < kMaxExplosions; ++i )
	{
		mExplosion[i].Update(deltaTime);
	}
	
	mExitScreen.Update(deltaTime);
	mCursor.Update(deltaTime);
	mStartButton1.Update(deltaTime);
	mQuitButton.Update(deltaTime);
	
	

	int bulletenemy = 1;
	int bulletplayer = 2;
	int enemyplayer = 3;
	FireBullets(deltaTime);
	CheckEnemyBulletCollision(bulletenemy,deltaTime);
	CheckPlayerBulletCollision(bulletplayer,deltaTime);
	CheckPlayerEnemyCollision(enemyplayer,deltaTime);

	
	//if(enemycheck==0)
	//{
	//	
	//	/*SAY WHICH WAVE YOU ARE ON*/
	//	mfilename1="wavedata2.txt";

	//	FileHandle.LoadLevel(mfilename1);
	//	InitializeWaveEnemy("EnemyTypeA");
	///*	 this needs to load in next wave. need to find a way to read numbers for the other waves*/

	//
	//}



	for(int i= 0 ;i<mLifecheck;++i)
	{
	  mLife[i].Update(deltaTime,mmap);

	 if(mLifecheck == 3)
	 {
	SVector2 life1(mCharacter.GetPosition());
	life1.x-=100;
	life1.y-=-100;
	SVector2 life2(mCharacter.GetPosition());
	life2.y-=-100;
	SVector2 life3(mCharacter.GetPosition());
	life3.x+=100;
	life3.y-=-100;
	mLife[0].SetPosition(life1);
	mLife[1].SetPosition(life2);
	mLife[2].SetPosition(life3);
	 }

	 else if(mLifecheck==2)
	 {
		SVector2 life1(mCharacter.GetPosition());
		life1.x-=100;
		life1.y-=-100;
		SVector2 life2(mCharacter.GetPosition());
		life2.y-=-100;
		
		mLife[0].SetPosition(life1);
		mLife[1].SetPosition(life2);
		

	 }

	  else if(mLifecheck==1)
	 {
		SVector2 life1(mCharacter.GetPosition());
		life1.x-=100;
		life1.y-=-100;
	
		
		mLife[0].SetPosition(life1);

	 }


	}

	mCharacter.Update(deltaTime, mmap);

	
	SpawnEnemy(deltaTime);

	NextState nextstate = None;
	
	if(mEnemyNum==0)
	{
	
		nextstate =Wavenumber2;

	}

	if(mStartButton1.IsPressed())
	{
		mGameContext.SetLevel(1);
		nextstate = Gameplay;
	}
	
	else if(mQuitButton.IsPressed())
	{
		nextstate = Quit;
	}
	return nextstate;
	
	
	if(Input_IsKeyPressed(Keys::ESCAPE))
	{
		nextstate = Frontend;

	}


	return nextstate;
}

void PlayState::Render()
{

	
	const int kWinWidth = IniFile_GetInt("WinWidth", 800);
	const int kWinHeight = IniFile_GetInt("WinHeight", 600);

	SVector2 viewTarget = mCharacter.GetPosition();
	SVector2 viewOffset;

	viewOffset.x = (viewTarget.x - (kWinWidth * 0.5f));
	viewOffset.y = (viewTarget.y - (kWinHeight * 0.5f));

	// screen viewing limits
	SVector2 limit;
	limit.x = (float) mmap.GetWidth() - kWinWidth;
	limit.y = (float) mmap.GetHeight() - kWinHeight;

	// cannot be smaller than 0, or bigger than limit
	viewOffset.x = Clamp(viewOffset.x, 0.0f, limit.x);
	viewOffset.y = Clamp(viewOffset.y, 0.0f, limit.y);

	mmap.Render(viewOffset);

	
	for (int i = 0; i < kMaxExplosions; ++i )
	{
		// true = additive blending
		mExplosion[i].SetOffset(-viewOffset);
		mExplosion[i].Render(true);
	}
	for (int i = 0; i < kMaxBullets; ++i )
	{
		mGun1[i].Render(viewOffset);
		SCircle circle = mGun1[i].GetBoundingCircle();
		circle.center -= viewOffset;
		Graphics_DebugCircle(circle, 0xff00ff);
	}

	for (int i = 0; i < kMaxEnemies; ++i )
	{
		mEnemyA[i].Render(viewOffset);
		SCircle circle = mEnemyA[i].GetBoundingCircle();
		circle.center -= viewOffset;
		Graphics_DebugCircle(circle, 0xff0000);
	}


	
	for(int i= 0 ;i<3;++i)
	{
	mLife[i].Render(viewOffset);
	}
	mCharacter.Render(viewOffset);

	if(IsGameOver)
	{
		
		mExitScreen.Render();
		mFont.SetColor(34,96,120);
		mFont.Print("GameOver!",100,100);
		mStartButton1.Render();
		mQuitButton.Render();
		mCursor.Render();
	}

	
}

